package com.yifushidai.config;

import com.alibaba.fastjson.JSON;
import com.yifushidai.utils.JsonStringUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;


/**
 * 去除参数头尾空格过滤器
 *
 * @author wxw
 */
@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean parmsFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setDispatcherTypes(DispatcherType.REQUEST);
        registration.setFilter(new ParamsFilter());
        registration.addUrlPatterns("/*");
        registration.setName("paramsFilter");
        registration.setOrder(Integer.MAX_VALUE - 1);
        return registration;
    }

    public class ParamsFilter implements Filter {
        @Override
        public void doFilter(ServletRequest arg0, ServletResponse arg1,
                             FilterChain arg2) throws IOException, ServletException {
            ParameterRequestWrapper parmsRequest = new ParameterRequestWrapper(
                    (HttpServletRequest) arg0);
            arg2.doFilter(parmsRequest, arg1);
        }

        @Override
        public void init(javax.servlet.FilterConfig arg0) throws ServletException {
        }

        @Override
        public void destroy() {
        }
    }

    public class ParameterRequestWrapper extends HttpServletRequestWrapper {

        private Map<String, String[]> params = new HashMap<String, String[]>();

        public ParameterRequestWrapper(HttpServletRequest request) {
            // 将request交给父类，以便于调用对应方法的时候，将其输出，其实父亲类的实现方式和第一种new的方式类似
            super(request);
            //将参数表，赋予给当前的Map以便于持有request中的参数
            Map<String, String[]> requestMap = request.getParameterMap();
//        System.out.println("转化前参数：" + JSON.toJSONString(requestMap));
            this.params.putAll(requestMap);
            this.modifyParameterValues();
//        System.out.println("转化后参数：" + JSON.toJSONString(params));
        }

        /**
         * 重写getInputStream方法  post类型的请求参数必须通过流才能获取到值
         */
        @Override
        public ServletInputStream getInputStream() throws IOException {
            //非json类型，直接返回
            if (!super.getHeader(HttpHeaders.CONTENT_TYPE).equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE)) {
                return super.getInputStream();
            }
            //为空，直接返回
            String json = IOUtils.toString(super.getInputStream(), "utf-8");
            if (StringUtils.isBlank(json)) {
                return super.getInputStream();
            }
//            System.out.println("转化前参数：" + json);
            Map<String, Object> map = JsonStringUtil.jsonStringToMap(json);
//            System.out.println("转化后参数：" + JSON.toJSONString(map));
            ByteArrayInputStream bis = new ByteArrayInputStream(JSON.toJSONString(map).getBytes("utf-8"));
            return new MyServletInputStream(bis);
        }

        /**
         * 将parameter的值去除空格后重写回去
         */
        public void modifyParameterValues() {
            Set<String> set = params.keySet();
            Iterator<String> it = set.iterator();
            while (it.hasNext()) {
                String key = (String) it.next();
                String[] values = params.get(key);
                values[0] = values[0].trim();
                params.put(key, values);
            }
        }

        /**
         * 重写getParameter 参数从当前类中的map获取
         */
        @Override
        public String getParameter(String name) {
            String[] values = params.get(name);
            if (values == null || values.length == 0) {
                return null;
            }
            return values[0];
        }

        /**
         * 重写getParameterValues
         */
        public String[] getParameterValues(String name) {//同上
            return params.get(name);
        }

        class MyServletInputStream extends ServletInputStream {
            private ByteArrayInputStream bis;

            public MyServletInputStream(ByteArrayInputStream bis) {
                this.bis = bis;
            }

            @Override
            public boolean isFinished() {
                return true;
            }

            @Override
            public boolean isReady() {
                return true;
            }

            @Override
            public void setReadListener(ReadListener listener) {

            }

            @Override
            public int read() throws IOException {
                return bis.read();
            }
        }

    }
}